package com.javabi.codeobject.java.block.method.adapt;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.javabi.codeobject.java.block.codeblock.IJavaCodeBlock;
import com.javabi.codeobject.java.block.codeblock.JavaCodeLines;
import com.javabi.codeobject.java.block.method.JavaMethod;
import com.javabi.codeobject.java.type.IJavaType;
import com.javabi.codeobject.java.type.JavaTypeContainer;
import com.javabi.codeobject.java.type.JavaTypeWithGenerics;
import com.javabi.codeobject.java.type.resolver.IJavaTypeResolver;

public class AdaptListMethod extends JavaMethod {

	private static IJavaType getFromCollectionType(IJavaTypeResolver resolver, IJavaType elementType) {
		IJavaType collectionType = resolver.getType(Collection.class);
		elementType = new JavaTypeContainer(elementType, true, false);
		return new JavaTypeWithGenerics(collectionType, elementType);
	}

	private static IJavaType getToListType(IJavaTypeResolver resolver, IJavaType elementType) {
		IJavaType listType = resolver.getType(List.class);
		return new JavaTypeWithGenerics(listType, elementType);
	}

	private final IJavaType fromType;
	private final IJavaType toType;

	public AdaptListMethod(IJavaType fromType, IJavaType toType, IJavaTypeResolver resolver) {
		super("adaptList", getToListType(resolver, toType));
		if (fromType == null) {
			throw new NullPointerException("fromType");
		}
		if (toType == null) {
			throw new NullPointerException("toType");
		}

		this.fromType = fromType;
		this.toType = toType;

		// Parameters
		getParameters().add("fromCollection", getFromCollectionType(resolver, fromType));

		// References
		getReferences().add(fromType);
		getReferences().add(toType);
		getReferences().add(Collection.class);
		getReferences().add(List.class);
		getReferences().add(ArrayList.class);

		// Method contents!
		setContents(createContents());
	}

	private IJavaCodeBlock createContents() {
		String toName = toType.getSimpleName();
		String fromName = fromType.getSimpleName();

		JavaCodeLines code = new JavaCodeLines();
		code.line("List<" + toName + "> toList = new ArrayList<" + toName + ">(fromCollection.size());");
		code.line("for (" + fromName + " from : fromCollection) {");
		code.line(1, toName + " to = adapt(from);");
		code.line(1, "toList.add(to);");
		code.line("}");
		code.line("return toList;");
		return code;
	}

}
